/**
 * this files imports or updates exisiting entries with pubchem compound properties
 */

import edu.ucdavis.genomics.metabolomics.binbase.connector.references.pubchem.PubchemCompoundSDFResolver
import org.apache.log4j.Logger
import edu.ucdavis.genomics.metabolomics.binbase.connector.references.sdf.InchFinder
import edu.ucdavis.genomics.metabolomics.binbase.connector.references.sdf.SdfToInchi
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import org.codehaus.groovy.grails.commons.ApplicationHolder as AH

import java.sql.Connection
import java.sql.Statement
import org.apache.log4j.Logger
import org.hibernate.Session
import org.hibernate.SessionFactory
import compound.repository.entries.Compound
import compound.repository.entries.PubchemCompound
import java.util.zip.GZIPInputStream
import util.CompoundHelper
//configuration file
def config = new ConfigSlurper().parse(new File('grails-app/conf/PathConfiguration.groovy').toURL())

Logger logger = Logger.getLogger("ImportPubchem")


if (params.file == null) {
  logger.info "using directory mode..."

  String tempDir = config.files.pubchem.compound

  FileHelper.workOnDir(tempDir, {File file ->
    PubchemInchiCompound sub = new PubchemInchiCompound()
    SdfToInchi.sdfToInchi(new FileInputStream(file), sub)

  }, logger, ".sdf")
}
else {
  logger.info "using direct file mode: ${params.file}"
  File file = new File(params.file)

  InputStream stream = null
  if (file.name.endsWith(".sdf.gz")) {

    stream = new GZIPInputStream(new FileInputStream(file))
  }

  else if (file.name.endsWith(".sdf")) {
    stream = new FileInputStream(file)

  }
  else {

    throw new RuntimeException("it needs to be a 'sdf' file or a 'sdf.gz' file ")
  }

  PubchemInchiCompound sub = new PubchemInchiCompound()
  SdfToInchi.sdfToInchi(new BufferedInputStream(stream), sub)

  stream.close()
}

/**
 * the actual import
 */
class PubchemInchiCompound implements InchFinder {

  public PubchemInchiCompound() {
  }


  public void foundInchi(String myInchi, Map<java.lang.Object, java.lang.Object> objectObjectMap) throws Exception {
    Logger logger = Logger.getLogger("ImportPubchem")
    logger.debug "checking if inchi is acceptable"

    logger.debug "checking if inchi is acceptable"
    if (myInchi != null && myInchi.size() > 0) {

      PubchemCompoundSDFResolver resolver = new PubchemCompoundSDFResolver();

      resolver.prepare(objectObjectMap)

      //logger.debug "loading compound from library ${resolver.getInchi()}"
      Compound compound = CompoundHelper.getCompound(resolver.getInchi(), resolver.getInchiKey(), logger)

      logger.debug "searching for dupliate pubchem cid's"
      PubchemCompound.findByCid(resolver.cid).each {PubchemCompound com ->

        if (com.compound.id != compound.id) {
          logger.warn "[pubchem] compound id ${com.compound.id} differs ${compound.id} , overwriting with new pubchem compound ${compound.id}, offending CID was ${com.cid}"

          Compound offender = CompoundHelper.getCompound(com.compound.id)

          logger.debug "removing...${offender.dbLinks.remove(com)}"
          logger.debug "deleting... ${com.delete(flush: true)}"
          CompoundHelper.saveCompound(offender, logger)
        }
        else {
          logger.debug "copound id ${com.compound.id}/${compound.id} is the same for cid ${com.cid}"
        }
      }

      CompoundHelper.updateCID(PubchemCompound.findAllByCompound(compound), logger, compound, resolver)

      //work on the smile codes
      CompoundHelper.updateSmiles(resolver.getIsoSmile(), compound, true)
      CompoundHelper.updateSmiles(resolver.getCanSmile(), compound, false)

      //work on iupac names
      List<String> iupacs = new Vector<String>()

      if (resolver.iupacCasName != null) {
        for (String s: resolver.iupacCasName) {
          if (!iupacs.contains(s)) {
            iupacs.add(s)
          }
        }
      }

      if (resolver.iupacName != null) {

        for (String s: resolver.iupacName) {
          if (!iupacs.contains(s)) {
            iupacs.add(s)
          }
        }
      }

      if (resolver.iupacSystematicName) {
        for (String s: resolver.iupacSystematicName) {
          if (!iupacs.contains(s)) {
            iupacs.add(s)
          }
        }
      }

      if (resolver.iupacTraditionalName) {
        for (String s: resolver.iupacTraditionalName) {
          if (!iupacs.contains(s)) {
            iupacs.add(s)
          }
        }
      }

      CompoundHelper.updateIUPACNames(iupacs, compound, logger)

      //save the compound again
      compound = CompoundHelper.saveCompound(compound, logger)


      CompoundHelper.aquireStatistic()

    }
  }
}
